package com.webex.ta.hydra.gui.wm;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;

/**
 * Created by Cisco WebEx.
 * User: vegaz
 * Date: 2010-10-22
 * Time: 15:37:46
 */
public class FloatingDecorator extends JDialog {
    private static final int ANCHOR_TOP = 1;
    private static final int ANCHOR_LEFT = 2;
    private static final int ANCHOR_BOTTOM = 4;
    private static final int ANCHOR_RIGHT = 8;

    private InternalDecorator internal;

    public FloatingDecorator(Frame owner, InternalDecorator internal) {
        super(owner);
        this.internal = internal;
        setUndecorated(true);
        JComponent cp = (JComponent) getContentPane();
        cp.setLayout(new BorderLayout());
        cp.add(new BorderItem(ANCHOR_TOP), BorderLayout.NORTH);
        cp.add(new BorderItem(ANCHOR_LEFT), BorderLayout.WEST);
        cp.add(new BorderItem(ANCHOR_BOTTOM), BorderLayout.SOUTH);
        cp.add(new BorderItem(ANCHOR_RIGHT), BorderLayout.EAST);
//        cp.add(Box.createRigidArea(new Dimension(400,300)));
        cp.add(internal, BorderLayout.CENTER);

        pack();
    }


    public WindowInfo getWindowInfo() {
        return internal.getWindowInfo();
    }

    private class BorderItem extends JPanel {
        private static final int DIVIDER_WIDTH = 4;
        private static final int RESIZER_WIDTH = 10;

        private final int anchor;
        private int motionMask;
        private Point lastPt;
        private boolean dragging;

        public BorderItem(final int anchor) {
            this.anchor = anchor;
            this.enableEvents(MouseEvent.MOUSE_EVENT_MASK | MouseEvent.MOUSE_MOTION_EVENT_MASK);
        }

        @Override
        public Dimension getPreferredSize() {
            Dimension size = super.getPreferredSize();
            if (ANCHOR_TOP == anchor || ANCHOR_BOTTOM == anchor) {
                size.height = DIVIDER_WIDTH;
            } else {
                size.width = DIVIDER_WIDTH;
            }
            return size;
        }

        @Override
        public void paint(Graphics g) {
            super.paint(g);

            if (ANCHOR_TOP == anchor) {
                g.setColor(Color.lightGray);
                g.drawLine(0, 0, getWidth() - 1, 0);
                g.drawLine(0, 0, 0, getHeight() - 1);
                g.setColor(Color.gray);
                g.drawLine(getWidth() - 1, 0, getWidth() - 1, getHeight() - 1);
            } else if (ANCHOR_LEFT == anchor) {
                g.setColor(Color.lightGray);
                g.drawLine(0, 0, 0, getHeight() - 1);
            } else if (ANCHOR_BOTTOM == anchor) {
                g.setColor(Color.lightGray);
                g.drawLine(0, 0, 0, getHeight() - 1);
                g.setColor(Color.gray);
                g.drawLine(0, getHeight() - 1, getWidth() - 1, getHeight() - 1);
                g.drawLine(getWidth() - 1, 0, getWidth() - 1, getHeight() - 1);
            } else {
                g.setColor(Color.gray);
                g.drawLine(getWidth() - 1, 0, getWidth() - 1, getHeight() - 1);
            }
        }

        @Override
        protected void processMouseEvent(MouseEvent e) {
            super.processMouseEvent(e);
            switch (e.getID()) {
                case MouseEvent.MOUSE_PRESSED:
                    lastPt = e.getPoint();
                    SwingUtilities.convertPointToScreen(lastPt, this);
                    setMotionMask(e.getPoint());
                    dragging = true;
                    break;
                case MouseEvent.MOUSE_RELEASED:
                    FloatingDecorator.this.validate();
                    FloatingDecorator.this.repaint();
                    dragging = false;
                    break;
                case MouseEvent.MOUSE_ENTERED:
                    if (!dragging)
                        setMotionMask(e.getPoint());
            }
        }

        @Override
        protected void processMouseMotionEvent(MouseEvent e) {
            super.processMouseMotionEvent(e);
            if (e.getID() == MouseEvent.MOUSE_DRAGGED && lastPt != null) {
                final Point newPoint = e.getPoint();
                SwingUtilities.convertPointToScreen(newPoint, this);

                final Rectangle oldBounds = FloatingDecorator.this.getBounds();
                final Rectangle newBounds = new Rectangle(oldBounds);

                if ((motionMask & ANCHOR_TOP) > 0) {
                    newPoint.y = Math.min(newPoint.y, oldBounds.y + oldBounds.height - 2 * DIVIDER_WIDTH);
                    final Point offset = new Point(newPoint.x - lastPt.x, newPoint.y - lastPt.y);
                    newBounds.y = oldBounds.y + offset.y;
                    newBounds.height = oldBounds.height - offset.y;
                }

                if ((motionMask & ANCHOR_LEFT) > 0) {
                    newPoint.x = Math.min(newPoint.x, oldBounds.x + oldBounds.width - 2 * DIVIDER_WIDTH);
                    final Point offset = new Point(newPoint.x - lastPt.x, newPoint.y - lastPt.y);
                    newBounds.x = oldBounds.x + offset.x;
                    newBounds.width = oldBounds.width - offset.x;
                }

                if ((motionMask & ANCHOR_BOTTOM) > 0) {
                    newPoint.y = Math.max(newPoint.y, oldBounds.y + 2 * DIVIDER_WIDTH);
                    final Point offset = new Point(newPoint.x - lastPt.x, newPoint.y - lastPt.y);
                    newBounds.height = oldBounds.height + offset.y;
                }

                if ((motionMask & ANCHOR_RIGHT) > 0) {
                    newPoint.x = Math.max(newPoint.x, oldBounds.x + 2 * DIVIDER_WIDTH);
                    final Point offset = new Point(newPoint.x - lastPt.x, newPoint.y - lastPt.y);
                    newBounds.width = oldBounds.width + offset.x;
                }
                FloatingDecorator.this.setBounds(newBounds.x, newBounds.y, newBounds.width, newBounds.height);
                lastPt = newPoint;
            } else if (e.getID() == MouseEvent.MOUSE_MOVED) {
                if (!dragging)
                    setMotionMask(e.getPoint());
            }
//            setMotionMask(e.getPoint());
//        switch(e.getID()) {
//
//        }
        }

        private void setMotionMask(final Point p) {
            motionMask = anchor;
            if (ANCHOR_TOP == anchor || ANCHOR_BOTTOM == anchor) {
                if (p.getX() < RESIZER_WIDTH)
                    motionMask |= ANCHOR_LEFT;
                else if (p.getX() > getWidth() - RESIZER_WIDTH)
                    motionMask |= ANCHOR_RIGHT;
            } else {
                if (p.getY() < RESIZER_WIDTH)
                    motionMask |= ANCHOR_TOP;
                else if (p.getY() > getHeight() - RESIZER_WIDTH)
                    motionMask |= ANCHOR_BOTTOM;
            }

            if (motionMask == ANCHOR_TOP)
                setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));
            else if (motionMask == (ANCHOR_TOP | ANCHOR_LEFT))
                setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR));
            else if (motionMask == (ANCHOR_LEFT))
                setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
            else if (motionMask == (ANCHOR_LEFT | ANCHOR_BOTTOM))
                setCursor(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));
            else if (motionMask == (ANCHOR_BOTTOM))
                setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR));
            else if (motionMask == (ANCHOR_BOTTOM | ANCHOR_RIGHT))
                setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
            else if (motionMask == (ANCHOR_RIGHT))
                setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
            else if (motionMask == (ANCHOR_RIGHT | ANCHOR_TOP))
                setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR));
        }
    }
}
